#ifndef HR_TBR_HPP
#define HR_TBR_HPP

#include "ap_int.h"
#include "ap_fixed.h"
#include "hls_stream.h"
#include "fpal.hpp" // 包含定点数运算逻辑库

// --- TBR Constants (moved here for module dependency) ---
const int TILE_WIDTH = 12; 
const int TILE_HEIGHT = 10;
const int TILE_PIXEL_COUNT = TILE_WIDTH * TILE_HEIGHT; // Tile 的总像素数
// 将屏幕分辨率定义为宏，以便 fpal.hpp 可以使用
#define SCREEN_WIDTH_PIX  320
#ifndef SCREEN_HEIGHT_PIX // 确保只定义一次，防止重复定义警告
#define SCREEN_HEIGHT_PIX 240
#endif // SCREEN_HEIGHT_PIX
const int MAX_SCREEN_WIDTH = SCREEN_WIDTH_PIX; // Use the macro
const int MAX_SCREEN_HEIGHT = SCREEN_HEIGHT_PIX; // Use the macro
// For 320x240, TILE_WIDTH=64, TILE_HEIGHT=64
// MAX_NUM_TILES_X = (320 + 64 - 1) / 64 = 383 / 64 = 5 (integer division) -> Should be 6 if ceiling is desired, but C++ integer division floors. For HLS, this will be ceil division.
// Using ceil: (320 + 63) / 64 = 6
// MAX_NUM_TILES_Y = (240 + 63) / 64 = 4
const int MAX_NUM_TILES_X = (MAX_SCREEN_WIDTH + TILE_WIDTH - 1) / TILE_WIDTH; // (320+63)/64 = 6
const int MAX_NUM_TILES_Y = (MAX_SCREEN_HEIGHT + TILE_HEIGHT - 1) / TILE_HEIGHT; // (240+63)/64 = 4

// Tile List Buffer 常量
// 降低每个 Tile 的最大三角形数量，以减少 TileListDataPacket 的位宽，从而节省 BRAM。
const int TILE_LIST_MAX_TRIANGLES_PER_TILE = 48; // 每个 Tile 最多关联 48 个三角形
const int TILE_LIST_MAX_TRIANGLES_PER_TILE_LOG2 = 6;
// 限制最大三角形数量为 511
const int MAX_NUM_TRIANGLES = 511; 
// 适应 511 个三角形 (log2(511) = 8.99..., 向上取整为 9)
const int TRIANGLE_ID_BITS = 9; 
// -----------------------------------------------------------

// -----------------------------------------------------------
// 输入结构体：从PS/DDR接收的定点数三角形光栅化参数
// -----------------------------------------------------------
struct raster_params_packet_fixed {
    fpal::fp_coord_t v0_x, v0_y;
    fpal::fp_coord_t v1_x, v1_y;
    fpal::fp_coord_t v2_x, v2_y;
    fpal::fp_z_buffer_t v0_z, v1_z, v2_z; 
    fpal::fp_coord_t edge0_A, edge0_B, edge0_C;
    fpal::fp_coord_t edge1_A, edge1_B, edge1_C;
    fpal::fp_coord_t edge2_A, edge2_B, edge2_C;
    fpal::fp_coord_t dzdx;
    fpal::fp_coord_t dzdy;
    fpal::fp_color_channel_t pure_color_R;
    fpal::fp_color_channel_t pure_color_G;
    fpal::fp_color_channel_t pure_color_B;
};

// -----------------------------------------------------------
// Tile Binning 模块输出的三角形参数包
// 这个结构体包含一个三角形的所有信息，以及它影响的Tile范围。
// 将会向所有 Tile Rasterizer 广播。
// NOTE: 此结构体将直接存储到 BRAM 中，供 Rasterizer 访问
// -----------------------------------------------------------
struct binned_triangle_packet_fixed {
    // Triangle setup parameters
    fpal::fp_coord_t v0_x_ref, v0_y_ref; // 参考点V0的坐标
    fpal::fp_z_buffer_t v0_z_ref;        // 参考点V0的深度

    fpal::fp_coord_t edge0_A, edge0_B, edge0_C;
    fpal::fp_coord_t edge1_A, edge1_B, edge1_C;
    fpal::fp_coord_t edge2_A, edge2_B, edge2_C;

    fpal::fp_coord_t dzdx;
    fpal::fp_coord_t dzdy;

    // 一个打包的 24 位颜色值
    ap_uint<24> packed_pure_color; 

    // Bounding Box in screen pixels
    fpal::fp_screen_pixel_idx_t min_x_px, max_x_px, min_y_px, max_y_px; 
    
    // Bounding Box in tiles (for binning to Tile List Buffer)
    ap_uint<8> min_tile_x, max_tile_x, min_tile_y, max_tile_y;
    
    bool is_valid_triangle; // 是否是有效三角形（非退化等）
};

// 用于在数据流中传输 tile_list_count 和 tile_list_data 的结构体
struct TileListDataPacket {
    ap_uint<8> tile_x; // 增加 tile_x 和 tile_y，以便接收方知道哪个 Tile 的数据
    ap_uint<8> tile_y;
    ap_uint<TILE_LIST_MAX_TRIANGLES_PER_TILE_LOG2> count;
    ap_uint<TRIANGLE_ID_BITS> data[TILE_LIST_MAX_TRIANGLES_PER_TILE];
};


// -----------------------------------------------------------
// HR_TBR 子模块声明 (现在是 Triangle Binning)
// 职责：从输入流读取一个三角形的参数，计算其屏幕空间包围盒和影响的 Tile 范围，
//       并将这些信息打包成 binned_triangle_packet_fixed 存储到 all_triangles_bram。
//       同时更新 Tile List Buffer (内部 BRAM) 并将其内容流化输出。
// -----------------------------------------------------------
void hr_tbr_binning_with_bram_write(
    hls::stream<raster_params_packet_fixed>& input_raster_params_stream,
    // all_triangles_bram 现在是一个输出流
    hls::stream<binned_triangle_packet_fixed>& s_binned_triangles_out, 
    hls::stream<fpal::fp_screen_pixel_idx_t>& s_max_x_res_in,
    hls::stream<fpal::fp_screen_pixel_idx_t>& s_max_y_res_in,
    hls::stream<ap_uint<16>>& s_num_triangles_to_process_in, // 从 stream 接收 num_triangles
    // 输出流，用于输出 tile_list_count 和 tile_list_data 的内容
    hls::stream<TileListDataPacket>& s_tile_list_out,
    hls::stream<fpal::fp_screen_pixel_idx_t>& s_max_x_res_out,
    hls::stream<fpal::fp_screen_pixel_idx_t>& s_max_y_res_out,
    hls::stream<ap_uint<16>>& s_num_triangles_to_process_out // 转发 num_triangles 给下一个模块
);

#endif // HR_TBR_HPP
